---
description: How to localize your browser extension with Plasmo
---

# Localization and Internationalization

Plasmo has built-in support for localization. These concepts should feel familiar to you if you've ever done this in any other Chrome extension.

Plasmo expects your locale files in any of these locations:

- `/locales/{lang}/messages.json`
- `/assets/_locales/{lang}/messages.json`
- `/assets/locales/{lang}/messages.json`

You will need to pick one and stick to it!

## English Example

Create a `locales/en/messages.json` file with a JSON mapping between a unique `key` and a locale object:

```json filename="locales/en/messages.json"
{
  "extensionName": {
    "message": "with-locales-i18n-en",
    "description": "Name of the extension."
  },
  "extensionDescription": {
    "message": "Example using locales + i18n!",
    "description": "Description of the extension."
  },
  "popup": {
    "message": "Logic is the beginning of wisdom, not the end.",
    "description": "Popup message."
  }
}
```

By default, Plasmo picks the first locale alphabetically available as default. However, you can specify a `default_locale` in your manifest like so:

```json filename="package.json"
{
  "manifest": {
    "default_locale": "en"
  }
}
```

Even more powerful, you can use environment variables inside your locale files:

```json filename="locales/en/messages.json"
{
  ...
  "popup": {
    "message": "Logic is the beginning of wisdom, not the end. - $PLASMO_PUBLIC_QUOTE_AUTHOR",
    "description": "Popup message."
  }
}
```

```ini filename=".env"
PLASMO_PUBLIC_QUOTE_AUTHOR=Spock
```

The locale files are monitored by Plasmo if they existed before the dev server started. Thus, you can change the locales file and see the changes in the browser without restarting the dev server.

## Usage

With the locale files in place, you can use the `i18n` API to localize your extension.

### Inside source code modules

To get the locale string inside your components, use the `i18n` API to get the locale message by its `key`:

```tsx filename="popup.tsx"
import { useState } from "react"

function IndexPopup() {
  const [data, setData] = useState("")

  return (
    <div
      style={{
        display: "flex",
        flexDirection: "column",
        padding: 16
      }}>
      <h1>
        Welcome to your <a href="https://www.plasmo.com">Plasmo</a> Extension!
      </h1>
      <h2>{chrome.i18n.getMessage("popup")}</h2>
      <input onChange={(e) => setData(e.target.value)} value={data} />
    </div>
  )
}

export default IndexPopup
```

### Inside package.json and manifest overrides

To reference a locale string inside your manifest overrides, wrap the key inside `__MSG_<key>__`:

```json filename="package.json"
{
  "name": "with-locales-i18n",
  "displayName": "__MSG_extensionName__",
  "version": "0.0.0",
  "description": "__MSG_extensionDescription__",
  "manifest": {
    "name": "__MSG_extensionName__"
  }
}
```

Please refer to the [Chrome i18n documentation](https://developer.chrome.com/extensions/i18n) for more information.

If you'd like to see an example showcasing locale, check out [with-locales-i18n](https://github.com/PlasmoHQ/examples/blob/main/with-locales-i18n) in the [Plasmo examples](https://github.com/PlasmoHQ/examples) repository.
